package com.travel.service.impl;

import cn.hutool.crypto.digest.BCrypt;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.travel.common.UserContext;
import com.travel.constant.UserConstant;
import com.travel.entity.dto.LoginRequestDTO;
import com.travel.entity.dto.UserRegisterDTO;
import com.travel.entity.dto.UserUpdateDTO;
import com.travel.entity.po.User;
import com.travel.entity.vo.LoginResponseVo;
import com.travel.entity.vo.UserVo;
import com.travel.exception.BusinessException;
import com.travel.exception.UserException;
import com.travel.mapper.UserMapper;
import com.travel.mapper.UserVoMapper;
import com.travel.result.PageResult;
import com.travel.result.ResultCode;
import com.travel.service.UserService;
import com.travel.utils.Base64ToImgNew;
import com.travel.utils.CopyUtil;
import com.travel.utils.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * @Author:Jasenon_ce
 * @Date: 2025/03/13/下午3:35
 */
@Service
@Slf4j
public class UserServiceImpl implements UserService {


    @Autowired
    private UserMapper userMapper;

    @Autowired
    Base64ToImgNew base64ToImgNew;

    private final UserVoMapper userVoMapper;

    public UserServiceImpl(UserMapper userMapper,UserVoMapper userVoMapper) {
        this.userMapper = userMapper;
        this.userVoMapper = userVoMapper;
    }

    @Override
    public PageResult<UserVo> getUsers(Integer pageNum, Integer pageSize) {
        // 构建查询条件
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(User::getId);

        // 执行分页查询
        Page<User> page = new Page<>(pageNum, pageSize);
        userMapper.selectPage(page, wrapper);

        // 转换为 UserVo 对象列表（不包含密码）
        List<UserVo> userVoList = page.getRecords().stream()
                .map(user -> {
                    UserVo userVo = null;
                    try {
                        userVo = CopyUtil.copy(user, UserVo.class);
                    } catch (InstantiationException e) {
                        throw new RuntimeException(e);
                    } catch (IllegalAccessException e) {
                        throw new RuntimeException(e);
                    }
                    // 确保不返回密码
                    return userVo;
                })
                .toList();

        // 构建分页结果
        return new PageResult<>(
                userVoList,
                page.getTotal(),
                page.getPages(),
                page.getCurrent(),
                page.getSize()
        );
    }

    public void updateUser(User user) {
        userMapper.updateById(user);
    }

    public void userRegister(UserRegisterDTO userRegisterVo) throws InstantiationException, IllegalAccessException {

        userRegisterVo.setPassword(BCrypt.hashpw(userRegisterVo.getPassword()));
        userRegisterVo.setRegistrationDate(new Date());
        userRegisterVo.setUserStatus(1);

        User user = CopyUtil.copy(userRegisterVo, User.class);
        try {
            log.info("正在注册新用户: {}", userRegisterVo);
            userMapper.insert(user);
            log.info("用户注册成功，用户名: {}", userRegisterVo.getUsername());
        }catch (Exception e){
            throw new UserException("用户名重复，操作失败");
        }
    }

    public LoginResponseVo userLogin(LoginRequestDTO loginRequestDTO){

        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getUsername, loginRequestDTO.getUsername());
        User user = userMapper.selectOne(wrapper);

        if (user == null) {
            throw new BusinessException(ResultCode.UNAUTHORIZED,UserConstant.USER_NOT_FOUND);
        }

        if (!BCrypt.checkpw(loginRequestDTO.getPassword(), user.getPassword())) {
            throw new BusinessException(ResultCode.UNAUTHORIZED,UserConstant.USER_ACCOUNT_OR_PASSWORD_ERROR);
        }

        // 更新最后登录时间
        user.setLastLogin(new Date());
        // 保存到数据库
        userMapper.updateById(user);

        // 确保JWT中包含用户ID和偏好语言
        log.debug("正在生成JWT令牌，包含用户ID: {} 和偏好语言: {}", user.getId(), user.getPreferredLanguage());
        
        String json = JSONObject.toJSONString(user);
        JSONObject jsonObject = JSONObject.parseObject(json);
        jsonObject.remove("password");
        json = jsonObject.toJSONString();
        String token = JWTUtil.generateToken(json);

        LoginResponseVo loginResponseVo = new LoginResponseVo();
        loginResponseVo.setUsername(user.getUsername());
        loginResponseVo.setToken(token);
        
        return loginResponseVo;
    }
    
    @Override
    public UserVo updateUserInfo(Long userId, UserUpdateDTO userUpdateDTO) {
        log.info("更新用户信息, userId: {}, updateInfo: {}", userId, userUpdateDTO);
        
        // 1. 查询用户是否存在
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BusinessException(ResultCode.NOT_FOUND, "用户不存在");
        }
        
        // 2. 更新用户信息，直接拷贝所有属性（前端会传递所有必要信息）
        try {
            BeanUtils.copyProperties(userUpdateDTO, user);
            
            // 3. 保存更新后的用户信息
            if (user.getAvatarUrl() == null || !user.getAvatarUrl().startsWith("http")){
                user.setAvatarUrl(base64ToImgNew.base64ToImgHerf(user.getAvatarUrl()));
                log.info("更新用户头像链接: {}", user.getAvatarUrl());
            }
            userMapper.updateById(user);
            
            // 4. 转换为UserVo并返回
            UserVo userVo = CopyUtil.copy(user, UserVo.class);
            return userVo;
        } catch (Exception e) {
            log.error("更新用户信息失败", e);
            throw new BusinessException("更新用户信息失败: " + e.getMessage());
        }
    }

    public UserVo getUser(){
        User user = userMapper.selectById(UserContext.getUserId());
        UserVo userVo = new UserVo();
        BeanUtils.copyProperties(user,userVo);
        return userVo;
    }
}
